#pragma once

#include <iostream>
#include <pthread.h>
#include <functional>
#include "Socket.hpp"

using func_t = std::function<std::string(std::string &, bool *Errocode)>;
class Tcpsever;
class ThreadData
{
public:
    ThreadData(Tcpsever *tcp_this, network::Socket *sockp) : _this(tcp_this), _sockp(sockp)
    {
    }

public:
    Tcpsever *_this;
    network::Socket *_sockp;
};

// typedef std::function<void()> func_t;
class Tcpsever
{
public:
    Tcpsever(uint16_t port, func_t handerrequest) : _port(port), _listensocket(new network::TcpSocket()), _Handlerequest(handerrequest)
    {
        _listensocket->BuildListenSocketMethod(_port, network::defaultbacklog);
    }
    static void *ThreadRun(void *args)
    {
        pthread_detach(pthread_self());
        std::string inbufferstream;
        ThreadData *td = static_cast<ThreadData *>(args);
        while (true)
        {
            bool ok = true;
            // 读取报文
            if (!td->_sockp->Recv(&inbufferstream, 1024))
            {
                break;
            }
            // 报文处理
            std::string send_string = td->_this->_Handlerequest(inbufferstream, &ok);
            if (ok)
            {
                if (!send_string.empty())
                {
                    // 发数据
                    td->_sockp->Send(send_string);
                }
            }
            else
            {
                break;
            }
        }
        td->_sockp->CloseSockfd();
        delete td->_sockp;
        delete td;
        return nullptr;
    }
    void Loop()
    {
        while (true)
        {
            std::string peerip;
            uint16_t peerport;
            network::Socket *newsock = _listensocket->AcceptConnection(peerip, peerport);
            if (newsock == nullptr)
                continue;
            std::cout << "获取新连接,sockfd: " << newsock->GetSockfd() << " client info " << peerip << ":" << peerport << std::endl;
            // sleep(5);
            // newsock->CloseSockfd();

            pthread_t tid;
            ThreadData *td = new ThreadData(this, newsock);
            pthread_create(&tid, nullptr, ThreadRun, td);
        }
    }
    ~Tcpsever()
    {
        delete _listensocket;
    }

private:
    int _port;
    network::Socket *_listensocket;
    func_t _Handlerequest;
};